package org.budo.dubbo.protocol.http.aop.permission.user;

import java.io.Serializable;
import java.lang.reflect.Method;

import org.budo.dubbo.protocol.http.authentication.AuthenticationCheckService.Fail;
import org.budo.dubbo.protocol.http.exception.remoting.AuthenticationCheckException;
import org.budo.dubbo.protocol.http.util.BudoReflectionUtil;
import org.budo.support.lang.util.ReflectUtil;
import org.budo.support.lang.util.StringUtil;

import lombok.extern.slf4j.Slf4j;

/**
 * @author lmw
 */
@Slf4j
public class AbstractUserPermissionCheckService implements UserPermissionCheckService {
    /**
     * @see org.budo.dubbo.protocol.http.authentication.AuthenticationCheckMethodInterceptor
     */
    @Override
    public void handleAuthFailed(Method method, Serializable userPrincipal) {
        log.error("#47 userPrincipal=" + userPrincipal + ", method=" + method);

        throw new AuthenticationCheckException(method, (Fail) userPrincipal); // 异常跳出流程
    }

    @Override
    public void handlePermissionFailed(Serializable _authenticationPrincipal, String permissionName) {
        throw new UserPermissionCheckException(_authenticationPrincipal, permissionName);
    }

    /**
     * 可以继承扩展这个方法
     */
    @Override
    public Boolean hasPermission(Serializable authenticationPrincipal, String permissionName) {
        log.info("#46 hasPermission, authenticationPrincipal=" + authenticationPrincipal + ", permissionName=" + permissionName);
        return false;
    }

    /**
     * 权限名称
     * 
     * @see org.budo.dubbo.protocol.http.aop.permission.user.UserPermissionCheck
     */
    @Override
    public String permissionName(Method method) {
        UserPermissionCheck annotation = BudoReflectionUtil.getMethodAnnotationCached(method, UserPermissionCheck.class);

        // 注解指定
        if (null != annotation && (annotation instanceof UserPermissionCheck) && StringUtil.isNotNullOrEmpty(annotation.value())) {
            return annotation.value();
        }

        // 默认为方法名
        String methodName = method.getName();

        Class<?> declaringClass = method.getDeclaringClass();
        Class<?>[] interfaces = declaringClass.getInterfaces();

        // 接口方法名
        for (Class<?> iface : interfaces) {
            if (ReflectUtil.hasMethod(iface, methodName, method.getParameterTypes())) {
                return iface.getSimpleName() + "." + methodName;
            }
        }

        // 类方法名
        return declaringClass.getSimpleName() + "." + methodName;
    }
}